#include "Config.h"
#include "ImageManager.h"
#include "MemTrack.h"

namespace bs
{
	const char* IMAGE_SESSION = "images";

	ImageManager::ImageManager()
	{
	}

	ImageManager::~ImageManager()
	{
		for(std::map<std::string, ImageInfo*>::iterator itr=this->images.begin();
			itr!=this->images.end(); ++itr)
		{
			delete itr->second;
		}

		for(std::map<std::string, ImageInfo*>::iterator itr=this->mirrors.begin();
			itr!=this->mirrors.end(); ++itr)
		{
			delete itr->second;
		}

		if(this->cfg)
			delete this->cfg;
	}

	ImageManager& ImageManager::Instance()
	{
		static ImageManager manager;

		return manager;
	}

	CImage* ImageManager::GetImage( const char* name, bool mirror /*= false*/ )
    {
		if(mirror)
		{
			return this->GetImage(name, this->mirrors, true);
		}
		else
		{
			return this->GetImage(name, this->images, false);
		}
	}

	void ImageManager::ReleaseImage( CImage* image )
	{
		if(!image)
			return;

		for(std::map<std::string, ImageInfo*>::iterator itr=this->images.begin();
			itr!=this->images.end(); ++itr)
		{
			ImageInfo* info = itr->second;
			if(info->image == image)
			{
				if(info->Release())
				{
					this->images.erase(itr);
					delete info;
				}

				return;
			}
		}

		for(std::map<std::string, ImageInfo*>::iterator itr=this->mirrors.begin();
			itr!=this->mirrors.end(); ++itr)
		{
			ImageInfo* info = itr->second;
			if(info->image == image)
			{
				if(info->Release())
				{
					this->mirrors.erase(itr);
					delete info;
				}

				return;
			}
		}
	}

	void ImageManager::SetConfigFile(const char* file/* = "image.ini" */)
	{
		if(!file || !::strlen(file))
			return;

		if(this->cfg)
			delete this->cfg;

		this->cfg = new Config;
		this->cfg->LoadFile(file);
	}

	CImage* ImageManager::GetImage( const char* name, std::map<std::string, ImageInfo*>& imageMap, bool mirror )
	{
		std::map<std::string, ImageInfo*>::iterator itr = imageMap.find(name);

		if(itr != imageMap.end())
		{
			return itr->second->GetImage();
		}

		std::string file = name;
		if(this->cfg)
		{
			file = this->cfg->GetValue(IMAGE_SESSION, name, "");
		}

		CImage* image = new CImage;
		image->Load(file.c_str());
		if(image->IsNull())
		{
			delete image;
			return NULL;
		}

		if(image->GetBPP() == 32)
		{
			BYTE* pBuf = (BYTE*)image->GetBits();

			int nHeight = image->GetHeight();
			int nWidth = image->GetWidth();
			for (int iy=0; iy<nHeight; ++iy)
			{
				BYTE *pPixel= (BYTE*)pBuf + image->GetPitch() * iy;

				for (int ix=0; ix<nWidth; ++ix)
				{
					if(pPixel[3] == 0)
					{
						::ZeroMemory(pPixel,3);
						pPixel+= 4;
						continue;
					}
					else if(pPixel[3] == 255)
					{
						pPixel+= 4;
						continue;
					}

					pPixel[0]= pPixel[0]*pPixel[3]/255;
					pPixel[1]= pPixel[1]*pPixel[3]/255;
					pPixel[2]= pPixel[2]*pPixel[3]/255;

					pPixel+= 4;
				}
			}

			if(mirror)
			{
				DWORD temp;
				for (int iy=0; iy<nHeight; ++iy)
				{
					DWORD* pPixel = (DWORD*)(pBuf + image->GetPitch() * iy);

					for (int ix=0; ix<nWidth/2; ++ix)
					{
						temp = pPixel[ix];
						pPixel[ix] = pPixel[nWidth-ix-1];
						pPixel[nWidth-ix-1] = temp;
					}
				}

			}
		}

		imageMap[name] = new ImageInfo(image);

		return image;
	}
}
